package cn.jbt.api.admin.service;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.jbt.api.admin.entity.SysMenu;
import cn.jbt.api.admin.entity.SysUser;
import cn.jbt.api.admin.entity.vo.UserInfoVO;
import cn.jbt.api.admin.event.SysLoginLogEvent;
import cn.jbt.api.admin.filter.LoginInfoAccessContext;
import cn.jbt.api.admin.repository.SysUserRepository;
import cn.jbt.common.UsernameAndPassword;
import cn.jbt.util.IpAddressUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.nio.charset.StandardCharsets;
import java.util.List;

@Service
@Slf4j
@AllArgsConstructor
public class SysLoginService {

    private final SysUserRepository sysUserRepository;
    private final ApplicationContext applicationContext;
    private final ISysMenuService iSysMenuService;
    private final ISysDeptService iSysDeptService;
    private final ISysPostService iSysPostService;
    private final ISysRoleService iSysRoleService;
    private final HttpServletRequest httpServletRequest;

    /**
     * <h2>根据账号和秘密登陆</h2>
     */
    public SaTokenInfo token(UsernameAndPassword usernameAndPassword) {

        SysUser sysUser = sysUserRepository
                .findFirstByUsernameAndStatus(usernameAndPassword.getUsername(), 1);
        if (null == sysUser) {
            applicationContext.publishEvent(
                    new SysLoginLogEvent(usernameAndPassword.getUsername(), 0, "登陆账号不存在",
                            httpServletRequest.getHeader("user-agent"),
                            IpAddressUtil.getIp(httpServletRequest)
                    ));
            throw new RuntimeException("登陆账号不存在");
        }

        // 校验密码
        String password = DigestUtils.md5DigestAsHex(String.format("%s%s",
                sysUser.getSalt(), usernameAndPassword.getPassword()).getBytes(StandardCharsets.UTF_8));
        if (!password.equals(sysUser.getPassword())) {
            applicationContext.publishEvent(
                    new SysLoginLogEvent(usernameAndPassword.getUsername(), 0, "登录账号或密码错误",
                            httpServletRequest.getHeader("user-agent"),
                            IpAddressUtil.getIp(httpServletRequest)
                    ));
            throw new RuntimeException("登录账号或密码错误");
        }

        StpUtil.login(sysUser.getId());

        applicationContext.publishEvent(
                new SysLoginLogEvent(usernameAndPassword.getUsername(), 1, "登录成功",
                        httpServletRequest.getHeader("user-agent"),
                        IpAddressUtil.getIp(httpServletRequest)
                ));

        return StpUtil.getTokenInfo();
    }

    /**
     * <h2>获取登陆信息和拥有的菜单</h2>
     */
    public UserInfoVO getUserInfo() {
        SysUser sysUser = sysUserRepository.findFirstById(
                LoginInfoAccessContext.getLoginInfo().getId());
        if (null == sysUser) {
            throw new RuntimeException("未登陆限制");
        }

        UserInfoVO userInfoVO = new UserInfoVO();
        userInfoVO.setId(sysUser.getId());
        userInfoVO.setUsername(sysUser.getUsername());
        userInfoVO.setMobile(sysUser.getMobile());
        userInfoVO.setNickname(sysUser.getNickname());
        userInfoVO.setAvatar(sysUser.getAvatar());
        userInfoVO.setEmail(sysUser.getEmail());
        userInfoVO.setSex(sysUser.getSex());
        userInfoVO.setDeptNames(iSysDeptService.getCascadeNamesById(sysUser.getDeptId(), "/"));

        List<String> postNames = iSysPostService.getNamesByUserId(sysUser.getId());
        if (CollectionUtils.isNotEmpty(postNames)) {
            userInfoVO.setDeptNames(String.join("/", postNames));
        }

        if (sysUser.getRoot().equals(1)) {
            userInfoVO.setMenuList(iSysMenuService.getAll(new SysMenu().setStatus(1)));

            userInfoVO.setRoleNames("超级管理员");
        } else {
            userInfoVO.setMenuList(iSysMenuService.getAllByUserId(LoginInfoAccessContext.getLoginInfo().getId()));

            List<String> roleNames = iSysRoleService.getNamesByUserId(sysUser.getId());
            if (CollectionUtils.isNotEmpty(roleNames)) {
                userInfoVO.setRoleNames(String.join("/", roleNames));
            }
        }

        return userInfoVO;
    }
}
